<template>
  <div class="course-scheduler">
    <!-- 组件内顶部悬浮班级列表 -->
    <div class="floating-class-bar">
      <div class="class-search">
        <el-input
          v-model="classSearchQuery.commodityName"
          placeholder="请输入课程名称"
          :prefix-icon="Search"
          clearable
          @change="searchClasses"
        />
      </div>
      <div class="classes-row">
        <div
          v-for="classItem in filteredClasses"
          :key="classItem.id"
          :draggable="true"
          @dragstart="handleDragStart($event, classItem)"
          @dragend="handleDragEnd"
          class="class-chip"
          :title="`${classItem.commodityName}-${classItem.classNumber}班 / ${classItem.teacherName || '未设置老师'}`"
        >
          <el-tag :type="getClassTagType(classItem.id)" size="small">
            <el-icon style="margin-right: 4px">
              <School />
            </el-icon>
            {{ classItem.commodityName }}-{{ classItem.classNumber }}班
          </el-tag>
          <el-text size="small" type="info">
            <el-icon style="margin-right: 4px">
              <User />
            </el-icon>
            {{ classItem.teacherName || '未设置老师' }}
          </el-text>
        </div>
      </div>
    </div>

    <!-- 主体内容区域 -->
    <div class="main-content">
      <div class="content-inner">
        <div class="top-settings">
          <el-card shadow="never" class="settings-card">
            <div class="settings-content">
              <div class="batch-mode-section">
                <el-text class="mode-label">批量排课模式</el-text>
                <el-radio-group v-model="batchMode" size="default">
                  <el-radio-button value="single">单次</el-radio-button>
                  <el-radio-button value="biweekly">每两周</el-radio-button>
                  <el-radio-button value="triweekly">每三周</el-radio-button>
                </el-radio-group>
              </div>

              <el-divider direction="vertical" />

              <div class="stats-section">
                <div class="stat-item">
                  <el-statistic title="总课程数" :value="totalCourses" />
                </div>
                <div class="stat-item">
                  <el-statistic title="上午" :value="morningCourses" />
                </div>
                <div class="stat-item">
                  <el-statistic title="下午" :value="afternoonCourses" />
                </div>
              </div>
            </div>
          </el-card>
        </div>

        <div class="schedule-main">
          <el-card shadow="hover" class="schedule-card">
            <template #header>
              <div class="schedule-header-content">
                <div class="card-header">
                  <el-icon>
                    <Calendar />
                  </el-icon>
                  <span>课程表</span>
                  <span style="color: #8a909c; font-size: small"
                    >拖动屏幕上下边栏班级、场地元件至课程表指定区域即可排课</span
                  >
                </div>

                <div class="header-right">
                  <!-- 年份下拉：纯数字回显、Element Plus 风格 -->
                  <el-select
                    v-model="currentYear"
                    placeholder="选择年份"
                    @change="handleYearChange"
                    class="year-select pill"
                    popper-class="year-select-popper"
                  >
                    <template #prefix>
                      <el-icon>
                        <Calendar />
                      </el-icon>
                    </template>
                    <el-option
                      v-for="year in availableYears"
                      :key="year"
                      :label="year"
                      :value="year"
                    />
                  </el-select>

                  <div class="week-controls">
                    <el-button
                      type="primary"
                      :icon="ArrowLeft"
                      @click="previousWeek"
                      circle
                      size="small"
                    />
                    <div class="week-info">
                      <div class="week-number-section">
                        <span class="week-label">第</span>
                        <span class="week-number">{{ currentWeek }}</span>
                        <span class="week-label">周</span>
                      </div>
                      <div class="week-date-section">
                        <span class="week-date">{{
                          formatWeekDateRange(currentYear, currentWeek)
                        }}</span>
                      </div>
                    </div>
                    <el-button
                      type="primary"
                      :icon="ArrowRight"
                      @click="nextWeek"
                      circle
                      size="small"
                    />
                  </div>
                </div>
              </div>
            </template>

            <div class="schedule-table-wrapper">
              <div class="schedule-table">
                <div class="schedule-header">
                  <div class="time-header">时间</div>
                  <div v-for="day in weekDays" :key="day.key" class="day-header">
                    {{ day.name }}
                  </div>
                </div>

                <div class="schedule-body">
                  <div class="time-period">
                    <div v-for="session in 2" :key="`morning-${session}`" class="time-row">
                      <div class="time-cell vertical-time">
                        <div class="session-number">第{{ session }}节</div>
                        <div class="time-range">{{ getMorningTime(session) }}</div>
                        <div class="period-indicator morning">上午</div>
                      </div>

                      <div
                        v-for="day in weekDays"
                        :key="`${day.key}-morning-${session}`"
                        class="schedule-cell"
                        :class="{
                          'has-content': getCellItems(day.key, 'morning', session).length,
                          'drag-over-course': isDragOverCell(day.key, 'morning', session, 'course'),
                          'drag-over-venue': isDragOverCell(day.key, 'morning', session, 'venue')
                        }"
                        @drop="handleDrop($event, day.key, 'morning', session)"
                        @dragover.prevent="handleDragOver($event, day.key, 'morning', session)"
                        @dragenter.prevent="handleDragEnter($event, day.key, 'morning', session)"
                        @dragleave="handleDragLeave($event, day.key, 'morning', session)"
                      >
                        <div class="cell-content">
                          <div
                            class="course-zone"
                            :class="{
                              'highlight-zone':
                                isDragOverCell(day.key, 'morning', session, 'course') &&
                                draggedClass
                            }"
                          >
                            <div
                              v-if="getCellItems(day.key, 'morning', session).length"
                              class="course-list"
                            >
                              <div
                                class="course-card"
                                v-for="(it, idx) in getCellItems(day.key, 'morning', session)"
                                :key="it.id || it.classId + '-' + idx"
                              >
                                <div class="row-1">
                                  <el-text size="small" class="mono">
                                    <el-icon style="margin-right: 4px">
                                      <User />
                                    </el-icon>
                                    {{ it.teacherName || '未设置老师' }}
                                  </el-text>
                                  <br />
                                  <el-tag
                                    :type="getClassTagType(it.classId)"
                                    closable
                                    @close="removeCourseAt(day.key, 'morning', session, idx)"
                                    size="small"
                                  >
                                    <el-tooltip placement="top">
                                      <template #content>{{ it.className }}</template>
                                      {{
                                        it.className.length > 6
                                          ? it.className.substring(0, 5) + '...'
                                          : it.className
                                      }}
                                    </el-tooltip>
                                  </el-tag>
                                  <el-text size="small" type="info" v-if="it.mode !== 'single'">
                                    {{ getModeText(it.mode) }}
                                  </el-text>
                                </div>

                                <div class="row-2">
                                  <template v-if="it.venue">
                                    <el-tag
                                      type="success"
                                      size="small"
                                      closable
                                      @close="removeVenueFor(day.key, 'morning', session, idx)"
                                    >
                                      <el-icon>
                                        <Location />
                                      </el-icon>
                                      <el-tooltip placement="top">
                                        <template #content>{{ it.venue }}</template>
                                        {{
                                          it.venue.length > 5
                                            ? it.venue.substring(0, 4) + '...'
                                            : it.venue
                                        }}
                                      </el-tooltip>
                                    </el-tag>
                                  </template>
                                  <template v-else>
                                    <el-tag type="info" size="small">未分配场地</el-tag>
                                  </template>
                                </div>
                              </div>
                            </div>
                            <div v-else class="empty-slot course-empty">
                              <el-icon>
                                <Plus />
                              </el-icon>
                              <span class="empty-text">拖入课程</span>
                            </div>
                          </div>

                          <div
                            class="venue-zone"
                            :class="{
                              'highlight-zone':
                                isDragOverCell(day.key, 'morning', session, 'venue') && draggedVenue
                            }"
                            style="display: none"
                          ></div>
                        </div>
                      </div>
                    </div>
                  </div>

                  <div class="time-period">
                    <div v-for="session in 2" :key="`afternoon-${session}`" class="time-row">
                      <div class="time-cell vertical-time">
                        <div class="session-number">第{{ session + 2 }}节</div>
                        <div class="time-range">{{ getAfternoonTime(session) }}</div>
                        <div class="period-indicator afternoon">下午</div>
                      </div>

                      <div
                        v-for="day in weekDays"
                        :key="`${day.key}-afternoon-${session}`"
                        class="schedule-cell"
                        :class="{
                          'has-content': getCellItems(day.key, 'afternoon', session).length,
                          'drag-over-course': isDragOverCell(
                            day.key,
                            'afternoon',
                            session,
                            'course'
                          ),
                          'drag-over-venue': isDragOverCell(day.key, 'afternoon', session, 'venue')
                        }"
                        @drop="handleDrop($event, day.key, 'afternoon', session)"
                        @dragover.prevent="handleDragOver($event, day.key, 'afternoon', session)"
                        @dragenter.prevent="handleDragEnter($event, day.key, 'afternoon', session)"
                        @dragleave="handleDragLeave($event, day.key, 'afternoon', session)"
                      >
                        <div class="cell-content">
                          <div
                            class="course-zone"
                            :class="{
                              'highlight-zone':
                                isDragOverCell(day.key, 'afternoon', session, 'course') &&
                                draggedClass
                            }"
                          >
                            <div
                              v-if="getCellItems(day.key, 'afternoon', session).length"
                              class="course-list"
                            >
                              <div
                                class="course-card"
                                v-for="(it, idx) in getCellItems(day.key, 'afternoon', session)"
                                :key="it.id || it.classId + '-' + idx"
                              >
                                <div class="row-1">
                                  <el-text size="small" class="mono">
                                    <el-icon style="margin-right: 4px">
                                      <User />
                                    </el-icon>
                                    {{ it.teacherName || '未设置老师' }}
                                  </el-text>
                                  <el-tag
                                    :type="getClassTagType(it.classId)"
                                    closable
                                    @close="removeCourseAt(day.key, 'afternoon', session, idx)"
                                    size="small"
                                  >
                                    <el-tooltip placement="top">
                                      <template #content>{{ it.className }}</template>
                                      {{
                                        it.className.length > 6
                                          ? it.className.substring(0, 5) + '...'
                                          : it.className
                                      }}
                                    </el-tooltip>
                                  </el-tag>
                                  <el-text size="small" type="info" v-if="it.mode !== 'single'">
                                    {{ getModeText(it.mode) }}
                                  </el-text>
                                </div>

                                <div class="row-2">
                                  <template v-if="it.venue">
                                    <el-tag
                                      type="success"
                                      size="small"
                                      closable
                                      @close="removeVenueFor(day.key, 'afternoon', session, idx)"
                                    >
                                      <el-icon>
                                        <Location />
                                      </el-icon>
                                      <el-tooltip placement="top">
                                        <template #content>{{ it.venue }}</template>
                                        {{
                                          it.venue.length > 5
                                            ? it.venue.substring(0, 4) + '...'
                                            : it.venue
                                        }}
                                      </el-tooltip>
                                    </el-tag>
                                  </template>
                                  <template v-else>
                                    <el-tag type="info" size="small">未分配场地</el-tag>
                                  </template>
                                </div>
                              </div>
                            </div>
                            <div v-else class="empty-slot course-empty">
                              <el-icon>
                                <Plus />
                              </el-icon>
                              <span class="empty-text">拖入课程</span>
                            </div>
                          </div>

                          <div
                            class="venue-zone"
                            :class="{
                              'highlight-zone':
                                isDragOverCell(day.key, 'afternoon', session, 'venue') &&
                                draggedVenue
                            }"
                            style="display: none"
                          ></div>
                        </div>
                      </div>
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </el-card>
        </div>
      </div>
    </div>

    <!-- 组件内底部悬浮场地列表 -->
    <div class="floating-venue-bar">
      <div class="venues-row">
        <div class="venue-search-fixed">
          <el-input
            v-model="venueSearchQuery.venueName"
            placeholder="请输入场地名称"
            :prefix-icon="Search"
            clearable
            @input="searchVenues"
          />
        </div>
        <div class="venue-list-scrollable">
          <div
            v-for="venue in displayVenues"
            :key="venue.id"
            :draggable="true"
            @dragstart="handleVenueDragStart($event, venue)"
            @dragend="handleDragEnd"
            class="venue-chip"
            :title="venue.venueNo"
          >
            <el-tag type="info" size="small">
              <el-icon style="margin-right: 4px">
                <Location />
              </el-icon>
              {{ venue.venueNo }}
            </el-tag>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, computed, reactive, onMounted } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import {
  ArrowLeft,
  ArrowRight,
  User,
  School,
  Calendar,
  Plus,
  Location,
  Search
} from '@element-plus/icons-vue'

import { VenueApi } from '@/api/train/venue'
import { CourseClassesApi } from '@/api/train/courseclasses'
import { ClassSettingApi } from '@/api/train/classsetting'

// ------- 类型 -------
type Period = 'morning' | 'afternoon'
type Mode = 'single' | 'biweekly' | 'triweekly'
type DayKey = 'monday' | 'tuesday' | 'wednesday' | 'thursday' | 'friday' | 'saturday' | 'sunday'

type ScheduleItem = {
  id?: number
  classId: number
  className: string
  teacherName?: string | null
  day: DayKey
  period: Period
  session: 1 | 2
  mode: Mode
  week: number
  year: number
  venue: string | null
  venueId: number | null
}

// ------- 映射 -------
const dayIndexToKey: Record<number, DayKey> = {
  1: 'monday',
  2: 'tuesday',
  3: 'wednesday',
  4: 'thursday',
  5: 'friday',
  6: 'saturday',
  7: 'sunday'
}
const dayKeyToIndex: Record<DayKey, number> = {
  monday: 1,
  tuesday: 2,
  wednesday: 3,
  thursday: 4,
  friday: 5,
  saturday: 6,
  sunday: 7
}
const toSequence = (period: Period, session: number) =>
  period === 'morning' ? session : session + 2
const fromSequence = (sequence: number): { period: Period; session: 1 | 2 } => {
  const seq = Number(sequence)
  if (seq <= 2) return { period: 'morning', session: seq as 1 | 2 }
  return { period: 'afternoon', session: (seq - 2) as 1 | 2 }
}
const cellKeyOf = (day: string, period: string, session: number) => `${day}-${period}-${session}`

// ------- 状态 -------
const currentYear = ref<number>(new Date().getFullYear())
const currentWeek = ref<number>(1)
const batchMode = ref<Mode>('single')
const schedule = ref<Record<string, ScheduleItem[]>>({})
const draggedClass = ref<any>(null)
const draggedVenue = ref<any>(null)
const classSearchQuery = reactive({ commodityName: undefined as string | undefined })
const dragOverCells = reactive<Record<string, boolean>>({})
const loading = ref<boolean>(true)

// ------- 数据存储（独立于搜索） -------
const venues = ref<any[]>([])
const allClasses = ref<any[]>([]) // 所有班级数据，不受搜索影响
const displayClasses = ref<any[]>([]) // 用于显示的班级数据

// ------- 数据字典（用于课程表显示） -------
const classDict = ref<Record<number, any>>({}) // 班级ID -> 班级信息
const venueDict = ref<Record<number, any>>({}) // 场地ID -> 场地信息

const weekDays = [
  { key: 'monday', name: '周一' },
  { key: 'tuesday', name: '周二' },
  { key: 'wednesday', name: '周三' },
  { key: 'thursday', name: '周四' },
  { key: 'friday', name: '周五' },
  {
    key: 'saturday',
    name: '周六'
  },
  { key: 'sunday', name: '周日' }
] as { key: DayKey; name: string }[]

// ------- 年份相关 -------
const availableYears = computed(() => {
  const currentYearValue = new Date().getFullYear()
  return Array.from({ length: 999 }, (_, i) => currentYearValue - 2 + i)
})

// ------- 年份周次计算 -------
const getFirstMondayOfYear = (year: number): Date => {
  const jan1 = new Date(year, 0, 1)
  const dayOfWeek = jan1.getDay()
  const daysToMonday = dayOfWeek === 0 ? 1 : 8 - dayOfWeek
  const firstMonday = new Date(year, 0, 1 + daysToMonday)
  return firstMonday
}

const getWeekDateRange = (year: number, weekNumber: number) => {
  const firstMonday = getFirstMondayOfYear(year)
  const start = new Date(firstMonday.getTime() + (weekNumber - 1) * 7 * 24 * 3600 * 1000)
  const end = new Date(start.getTime() + 6 * 24 * 3600 * 1000)
  return { start, end }
}

const formatWeekDateRange = (year: number, weekNumber: number) => {
  const { start, end } = getWeekDateRange(year, weekNumber)
  const f = (d: Date) => `${d.getMonth() + 1}月${d.getDate()}日`
  return `${f(start)} - ${f(end)}`
}

const getCurrentWeekOfYear = () => {
  const now = new Date()
  const currentYearValue = now.getFullYear()
  const firstMonday = getFirstMondayOfYear(currentYearValue)
  const diffTime = now.getTime() - firstMonday.getTime()
  const diffWeeks = Math.floor(diffTime / (7 * 24 * 3600 * 1000)) + 1
  return Math.max(1, diffWeeks)
}

// ------- 获取具体日期 -------
const getSpecificDate = (year: number, week: number, dayKey: DayKey): Date => {
  const { start: weekStart } = getWeekDateRange(year, week)
  const dayOffset = dayKeyToIndex[dayKey] - 1 // 周一为0，周日为6
  const specificDate = new Date(weekStart.getTime() + dayOffset * 24 * 3600 * 1000)
  return specificDate
}

// ------- 将后端一条设置转成具体日期（用于前向删除的时间比较） -------
const getDateOfSetting = (s: any): Date | null => {
  const year = Number(s.yearNumber)
  const week = Number(s.weekly)
  const dayIdx = Number(s.weekNumber)
  const dayKey = dayIndexToKey[dayIdx as 1 | 2 | 3 | 4 | 5 | 6 | 7]
  if (!year || !week || !dayKey) return null
  return getSpecificDate(year, week, dayKey)
}


// ------- 开课时间判断（修改为按具体日期判断） -------
const checkCourseStartTime = (
  classItem: any,
  targetYear: number,
  targetWeek: number,
  dayKey: DayKey
): boolean => {
  if (!classItem.beginTime) return true // 没有开课时间限制则允许

  const beginDate = new Date(classItem.beginTime)
  const targetDate = getSpecificDate(targetYear, targetWeek, dayKey)

  // 只比较日期，不比较时间
  const beginDateOnly = new Date(beginDate.getFullYear(), beginDate.getMonth(), beginDate.getDate())
  const targetDateOnly = new Date(
    targetDate.getFullYear(),
    targetDate.getMonth(),
    targetDate.getDate()
  )

  return targetDateOnly >= beginDateOnly
}

const checkCourseEndTime = (
  classItem: any,
  targetYear: number,
  targetWeek: number,
  dayKey: DayKey
): boolean => {
  if (!classItem.endTime) return true // 没有结课时间限制则允许

  const endDate = new Date(classItem.endTime)
  const targetDate = getSpecificDate(targetYear, targetWeek, dayKey)

  // 只比较日期，不比较时间
  const endDateOnly = new Date(endDate.getFullYear(), endDate.getMonth(), endDate.getDate())
  const targetDateOnly = new Date(
    targetDate.getFullYear(),
    targetDate.getMonth(),
    targetDate.getDate()
  )

  return targetDateOnly <= endDateOnly
}

// ------- 计算属性 -------
const filteredClasses = computed(() => {
  const q = (classSearchQuery.commodityName ?? '').toString().trim().toLowerCase()
  if (!q) return displayClasses.value
  return displayClasses.value.filter((c) =>
    (c.commodityName ?? '').toString().toLowerCase().includes(q)
  )
})

const totalCourses = computed(() =>
  Object.values(schedule.value).reduce((acc, arr) => acc + arr.length, 0)
)
const morningCourses = computed(
  () =>
    Object.values(schedule.value)
      .flat()
      .filter((i) => i.period === 'morning').length
)
const afternoonCourses = computed(
  () =>
    Object.values(schedule.value)
      .flat()
      .filter((i) => i.period === 'afternoon').length
)

// ------- 工具函数 -------
const getCellItems = (day: DayKey, period: Period, session: number) =>
  schedule.value[cellKeyOf(day, period, session)] ?? []
const setCellItems = (day: DayKey, period: Period, session: number, items: ScheduleItem[]) => {
  schedule.value[cellKeyOf(day, period, session)] = items
}
const getClassTagType = (classId: number) =>
  (['success', 'info', 'warning', 'danger', 'primary'] as const)[classId % 5]
const getModeText = (mode: Mode) =>
  ({
    single: '单次',
    biweekly: '每两周',
    triweekly: '每三周'
  })[mode]

import {DICT_TYPE, getDictLabel} from '@/utils/dict'


const getMorningTime = (s: number) => [getDictLabel(DICT_TYPE.TRAIN_COURSE_TIME,0), getDictLabel(DICT_TYPE.TRAIN_COURSE_TIME,1)][s - 1]
const getAfternoonTime = (s: number) => [getDictLabel(DICT_TYPE.TRAIN_COURSE_TIME,2), getDictLabel(DICT_TYPE.TRAIN_COURSE_TIME,3)][s - 1]

// ------- 数据加载 -------
const loadBasicData = async () => {
  try {
    // 使用新的列表API，不传递分页参数
    const [venueRes, classRes] = await Promise.all([
      VenueApi.getVenueList({}),
      CourseClassesApi.getCourseClassesList({})
    ])

    // 处理返回数据 - 适配不同的返回格式
    venues.value = venueRes?.data || venueRes?.list || venueRes || []
    allClasses.value = classRes?.data || classRes?.list || classRes || []
    displayClasses.value = [...allClasses.value]

    // 构建数据字典
    classDict.value = {}
    allClasses.value.forEach((cls) => {
      classDict.value[cls.id] = cls
    })

    venueDict.value = {}
    venues.value.forEach((venue) => {
      venueDict.value[venue.id] = venue
    })

    console.log('基础数据加载完成:', {
      venues: venues.value.length,
      classes: allClasses.value.length
    })

    displayVenues.value = [...venues.value]
  } catch (e) {
    console.error('Failed to load basic data:', e)
    ElMessage.error('加载基础数据失败，请稍后重试')
  }
}

const searchClasses = async () => {
  try {
    // 使用新的列表API进行搜索
    const searchParams = classSearchQuery.commodityName
      ? { commodityName: classSearchQuery.commodityName }
      : {}

    const res = await CourseClassesApi.getCourseClassesList(searchParams)

    // 处理返回数据 - 适配不同的返回格式
    displayClasses.value = res?.data || res?.list || res || []

    console.log('班级搜索完成:', {
      query: classSearchQuery.commodityName,
      results: displayClasses.value.length
    })
  } catch (e) {
    console.error('Failed to search classes:', e)
    ElMessage.error('搜索班级失败，请稍后重试')
  }
}

// ------- 数据回灌 -------
const hydrateScheduleFromBackend = (settings: any[]) => {
  schedule.value = {}
  for (const s of settings) {
    const dayKey = dayIndexToKey[Number(s.weekNumber)]
    if (!dayKey) continue
    const { period, session } = fromSequence(Number(s.sequence))
    const key = cellKeyOf(dayKey, period, session)

    const classItem = classDict.value[s.classesId]
    const className = classItem
      ? `${classItem.commodityName}-${classItem.classNumber}班`
      : `班级#${s.classesId}`
    const teacherName = classItem?.teacherName ?? null

    const venueItem = venueDict.value[s.venueId]
    const venueNo = venueItem?.venueNo ?? null

    const item: ScheduleItem = {
      id: s.id,
      classId: s.classesId,
      className,
      teacherName,
      day: dayKey,
      period,
      session,
      mode: 'single',
      week: Number(s.weekly),
      year: Number(s.yearNumber),
      venue: venueNo,
      venueId: s.venueId || null
    }
    if (!schedule.value[key]) schedule.value[key] = []
    schedule.value[key].push(item)
  }
}

const getScheduleList = async () => {
  loading.value = true
  try {
    const settingRes: any = await ClassSettingApi.getClassSettingList({
      weekly: String(currentWeek.value),
      yearNumber: String(currentYear.value)
    })
    const settings: any[] = Array.isArray(settingRes)
      ? settingRes
      : Array.isArray(settingRes?.data)
        ? settingRes.data
        : []
    if (settings.length) {
      hydrateScheduleFromBackend(settings)
    } else {
      schedule.value = {}
    }

    console.log('课程表数据加载完成:', {
      year: currentYear.value,
      week: currentWeek.value,
      scheduleCount: Object.keys(schedule.value).length
    })
  } catch (e) {
    console.error('Failed to load schedule:', e)
    schedule.value = {}
    ElMessage.error('加载课程表失败，请稍后重试')
  } finally {
    loading.value = false
  }
}

// ------- 周期周次计算（修改为按具体日期判断） -------
const calculateScheduleWeeksByClass = (
  classItem: any,
  startWeek: number,
  startYear: number,
  mode: Mode,
  dayKey: DayKey
) => {
  const weeks: { week: number; year: number }[] = []

  if (mode === 'single') {
    if (
      checkCourseStartTime(classItem, startYear, startWeek, dayKey) &&
      checkCourseEndTime(classItem, startYear, startWeek, dayKey)
    ) {
      weeks.push({ week: startWeek, year: startYear })
    }
  } else {
    const step = mode === 'biweekly' ? 2 : 3
    let currentWeek = startWeek
    let currentYear = startYear

    for (let i = 0; i < 12; i++) {
      // 最多12次
      if (
        checkCourseStartTime(classItem, currentYear, currentWeek, dayKey) &&
        checkCourseEndTime(classItem, currentYear, currentWeek, dayKey)
      ) {
        weeks.push({ week: currentWeek, year: currentYear })
      }

      currentWeek += step
      if (currentWeek > 52) {
        // 简单处理跨年
        currentWeek = currentWeek - 52
        currentYear += 1
      }
    }
  }

  return weeks
}

// ------- 事件处理 -------
const handleYearChange = () => {
  currentWeek.value = 1
  getScheduleList()
}

const previousWeek = () => {
  if (currentWeek.value > 1) {
    currentWeek.value--
  } else {
    currentWeek.value = 52
    currentYear.value--
  }
  getScheduleList()
}

const nextWeek = () => {
  if (currentWeek.value < 52) {
    currentWeek.value++
  } else {
    currentWeek.value = 1
    currentYear.value++
  }
  getScheduleList()
}

// ------- 拖拽交互 -------
const handleDragStart = (event: DragEvent, item: any) => {
  draggedClass.value = item
  draggedVenue.value = null
  event.dataTransfer?.setData('type', 'class')
  event.dataTransfer!.effectAllowed = 'move'
}
const handleVenueDragStart = (event: DragEvent, venue: any) => {
  draggedVenue.value = venue
  draggedClass.value = null
  event.dataTransfer?.setData('type', 'venue')
  event.dataTransfer!.effectAllowed = 'move'
}
const handleDragEnd = () => {
  Object.keys(dragOverCells).forEach((k) => delete dragOverCells[k])
}
const handleDragOver = (event: DragEvent, day: DayKey, period: Period, session: number) => {
  event.preventDefault()
  const type = event.dataTransfer?.getData('type') || (draggedClass.value ? 'class' : 'venue')
  const cellKey = `${day}-${period}-${session}`
  if (type === 'class' && draggedClass.value) dragOverCells[`${cellKey}-course`] = true
  else if (type === 'venue' && draggedVenue.value) dragOverCells[`${cellKey}-venue`] = true
}
const handleDragEnter = (event: DragEvent, day: DayKey, period: Period, session: number) => {
  event.preventDefault()
  const cellKey = `${day}-${period}-${session}`
  if (draggedClass.value) dragOverCells[`${cellKey}-course`] = true
  else if (draggedVenue.value) dragOverCells[`${cellKey}-venue`] = true
}
const handleDragLeave = (event: any, day: DayKey, period: Period, session: number) => {
  const related = event.relatedTarget
  if (!event.currentTarget.contains(related)) {
    const cellKey = `${day}-${period}-${session}`
    delete dragOverCells[`${cellKey}-course`]
    delete dragOverCells[`${cellKey}-venue`]
  }
}
const isDragOverCell = (day: DayKey, period: Period, session: number, type: 'course' | 'venue') =>
  !!dragOverCells[`${day}-${period}-${session}-${type}`]

// ------- Drop 处理（修改为按具体日期判断） -------
const handleDrop = async (event: DragEvent, day: DayKey, period: Period, session: number) => {
  event.preventDefault()
  event.stopPropagation()

  const cellKey = `${day}-${period}-${session}`
  delete dragOverCells[`${cellKey}-course`]
  delete dragOverCells[`${cellKey}-venue`]

  // 拖入课程
  if (draggedClass.value) {
    const items = getCellItems(day, period, session)

    // 1) 同一班级重复
    if (items.some((it) => it.classId === draggedClass.value.id)) {
      ElMessage.warning('该时间已包含此班级')
      draggedClass.value = null
      return
    }

    // 2) 老师冲突：同一时间同一老师不得重复
    const teacherName = draggedClass.value.teacherName ?? null
    if (teacherName && items.some((it) => it.teacherName === teacherName)) {
      ElMessage.error('该时间段老师已有安排')
      draggedClass.value = null
      return
    }

    // 3) 开课时间检查（修改为传入具体的星期几）
    if (!checkCourseStartTime(draggedClass.value, currentYear.value, currentWeek.value, day)) {
      const targetDate = getSpecificDate(currentYear.value, currentWeek.value, day)
      const beginDate = new Date(draggedClass.value.beginTime)
      ElMessage.error(
        `该课程开课时间为${beginDate.toLocaleDateString()}，不能在${targetDate.toLocaleDateString()}排课`
      )
      draggedClass.value = null
      return
    }

    if (!checkCourseEndTime(draggedClass.value, currentYear.value, currentWeek.value, day)) {
      const targetDate = getSpecificDate(currentYear.value, currentWeek.value, day)
      const endDate = new Date(draggedClass.value.endTime)
      ElMessage.error(
        `该课程结课时间为${endDate.toLocaleDateString()}，不能在${targetDate.toLocaleDateString()}排课`
      )
      draggedClass.value = null
      return
    }

    const scheduleWeeks = calculateScheduleWeeksByClass(
      draggedClass.value,
      currentWeek.value,
      currentYear.value,
      batchMode.value,
      day
    )
    if (!scheduleWeeks.length) {
      ElMessage.warning('该班级在当前时间范围内无法排课，请检查班级的开课和结课时间')
      draggedClass.value = null
      return
    }

    if (batchMode.value !== 'single') {
      const weekTexts = scheduleWeeks.map((w) => `${w.year}年第${w.week}周`)
      const msg =
        `将为 "${draggedClass.value.commodityName}-${draggedClass.value.classNumber}班" 批量排课：\n` +
        `模式：${getModeText(batchMode.value)}\n` +
        `周次：${weekTexts.join('、')}\n` +
        `共 ${scheduleWeeks.length} 次\n\n确认排课？`
      const ok = await ElMessageBox.confirm(msg, '批量排课确认', {
        confirmButtonText: '确认排课',
        cancelButtonText: '取消',
        type: 'info'
      }).catch(() => false)
      if (!ok) {
        draggedClass.value = null
        return
      }
    }

    let success = 0,
      fail = 0
    for (const { week, year } of scheduleWeeks) {
      try {
        const payload = {
          classesId: draggedClass.value.id,
          venueId: null,
          weekly: String(week),
          weekNumber: String(dayKeyToIndex[day]),
          sequence: String(toSequence(period, session)),
          yearNumber: String(year)
        }
        const res = await ClassSettingApi.createClassSetting(payload)
        const newId = res?.data ?? res
        if (newId) {
          success++
          if (week === currentWeek.value && year === currentYear.value) {
            const newItem: ScheduleItem = {
              id: newId,
              classId: draggedClass.value.id,
              className: `${draggedClass.value.commodityName}-${draggedClass.value.classNumber}班`,
              teacherName,
              day,
              period,
              session: session as 1 | 2,
              mode: batchMode.value,
              week,
              year,
              venue: null,
              venueId: null
            }
            setCellItems(day, period, session, [...items, newItem])
          }
        }
      } catch (e) {
        console.error('createClassSetting error:', e)
        fail++
      }
    }

    if (success > 0) {
      ElMessage.success(
        batchMode.value === 'single'
          ? '课程已添加'
          : `批量排课完成：成功${success}次${fail ? `，失败${fail}次` : ''}`
      )
    } else {
      ElMessage.error('排课失败，请重试')
    }

    draggedClass.value = null
    return
  }

  // 拖入场地
  if (draggedVenue.value) {
    const items = getCellItems(day, period, session)
    if (!items.length) {
      ElMessage.warning('请先拖入课程，再分配场地')
      draggedVenue.value = null
      return
    }

    // 默认给"最近一次添加"的课程分配场地
    const target = items[items.length - 1]

    // 场地冲突：同一格内，场地唯一
    if (items.some((it) => it.venueId === draggedVenue.value.id && it.id !== target.id)) {
      ElMessage.error('该时间该场地已被占用')
      draggedVenue.value = null
      return
    }

    if (!target.id) {
      ElMessage.error('课程数据异常，请重新拖入课程')
      draggedVenue.value = null
      return
    }

    if (target.mode !== 'single') {
      await handleBatchVenueAssignment(
        target.classId,
        day,
        period,
        session,
        target.mode,
        draggedVenue.value
      )
      const updated = items.map((it) =>
        it.classId === target.classId
          ? {
              ...it,
              venueId: draggedVenue.value.id,
              venue: draggedVenue.value.venueNo
            }
          : it
      )
      setCellItems(day, period, session, updated)
      ElMessage.success('场地已批量分配')
    } else {
      const old = { ...target }
      target.venueId = draggedVenue.value.id
      target.venue = draggedVenue.value.venueNo
      try {
        const data = {
          id: target.id,
          classesId: target.classId,
          venueId: target.venueId,
          weekly: String(target.week),
          weekNumber: String(dayKeyToIndex[target.day]),
          sequence: String(toSequence(target.period, target.session)),
          yearNumber: String(target.year)
        }
        await ClassSettingApi.updateClassSetting(data)
        const newArr = [...items.slice(0, -1), target]
        setCellItems(day, period, session, newArr)
        ElMessage.success('场地已分配')
      } catch (e) {
        const newArr = [...items.slice(0, -1), old]
        setCellItems(day, period, session, newArr)
        ElMessage.error('分配场地失败')
      }
    }

    draggedVenue.value = null
  }
}

// ------- 批量场地分配 -------
const handleBatchVenueAssignment = async (
  classId: number,
  day: DayKey,
  period: Period,
  session: number,
  mode: Mode,
  venue: any
) => {
  try {
    const allSettings = await ClassSettingApi.getClassSettingList({
      classesId: classId,
      weekNumber: String(dayKeyToIndex[day]),
      sequence: String(toSequence(period, session))
    })
    const settings: any[] = Array.isArray(allSettings)
      ? allSettings
      : Array.isArray(allSettings?.data)
        ? allSettings.data
        : []
    for (const s of settings) {
      await ClassSettingApi.updateClassSetting({
        id: s.id,
        classesId: s.classesId,
        venueId: venue.id,
        weekly: s.weekly,
        weekNumber: s.weekNumber,
        sequence: s.sequence,
        yearNumber: s.yearNumber
      })
    }
  } catch (e) {
    console.error('handleBatchVenueAssignment error:', e)
    ElMessage.error('批量场地分配失败，请重试')
  }
}

// ------- 删除/移除（增强：支持“从本次起至结课”） -------
const removeCourseAt = async (day: DayKey, period: Period, session: number, idx: number) => {
  const arr = getCellItems(day, period, session)
  const item = arr[idx]
  if (!item) return

  // 弹框双选：确认键=仅删本次；取消键=从本次起至结课；关闭则不操作
  const action = await ElMessageBox.confirm(
    `请选择删除范围：\n\n• 仅删除本次排课\n• 从本次起到本班级结课（包含本次）`,
    '确认删除',
    {
      confirmButtonText: '仅删除本次',
      cancelButtonText: '从本次起至结课',
      type: 'warning',
      distinguishCancelAndClose: true
    }
  ).then(() => 'confirm').catch((act: any) => act) // 'cancel' | 'close'

  if (action === 'close') return

  if (action === 'confirm') {
    // 仅删除本次
    if (!item.id) {
      ElMessage.error('课程数据异常，请重试')
      return
    }
    await handleSingleCourseRemoval(item.id, day, period, session, idx)
    return
  }

  if (action === 'cancel') {
    // 从本次起至结课
    await handleForwardCourseRemoval(item, day, period, session)
    return
  }
}


const handleSingleCourseRemoval = async (
  id: number,
  day: DayKey,
  period: Period,
  session: number,
  idx: number
) => {
  try {
    await ClassSettingApi.deleteClassSetting(id)
    const arr = getCellItems(day, period, session)
    arr.splice(idx, 1)
    setCellItems(day, period, session, [...arr])
    ElMessage.success('课程已删除')
  } catch (e) {
    ElMessage.error('删除课程失败')
  }
}

const handleBatchCourseRemoval = async (
  classId: number,
  day: DayKey,
  period: Period,
  session: number
) => {
  try {
    const allSettings = await ClassSettingApi.getClassSettingList({
      classesId: classId,
      weekNumber: String(dayKeyToIndex[day]),
      sequence: String(toSequence(period, session))
    })
    const settings: any[] = Array.isArray(allSettings)
      ? allSettings
      : Array.isArray(allSettings?.data)
        ? allSettings.data
        : []
    let ok = 0,
      fail = 0
    for (const s of settings) {
      try {
        await ClassSettingApi.deleteClassSetting(s.id)
        ok++
      } catch {
        fail++
      }
    }
    if (!ok) throw new Error('no success')
    ElMessage.success(`批量删除完成：成功${ok}次${fail ? `，失败${fail}次` : ''}`)
  } catch (e) {
    ElMessage.error('批量删除失败，请重试')
  }
}

// ------- 从本次起至结课 批量删除 -------
const handleForwardCourseRemoval = async (
  baseItem: ScheduleItem, // 当前格子里被点掉的那条
  day: DayKey,
  period: Period,
  session: number
) => {
  try {
    // 取该班级在相同星期几/节次的所有设置
    const allSettings = await ClassSettingApi.getClassSettingList({
      classesId: baseItem.classId,
      weekNumber: String(dayKeyToIndex[day]),
      sequence: String(toSequence(period, session))
    })

    const settings: any[] = Array.isArray(allSettings)
      ? allSettings
      : Array.isArray(allSettings?.data)
        ? allSettings.data
        : []

    // 当前点击这次的“具体日期”
    const currentDate = getSpecificDate(baseItem.year, baseItem.week, day)
    const currentDateOnly = new Date(
      currentDate.getFullYear(),
      currentDate.getMonth(),
      currentDate.getDate()
    )

    // 该班级的结课日期（若无结课时间则视为无限未来）
    const cls = classDict.value[baseItem.classId]
    const endDate = cls?.endTime ? new Date(cls.endTime) : null
    const endDateOnly = endDate
      ? new Date(endDate.getFullYear(), endDate.getMonth(), endDate.getDate())
      : null

    // 过滤：日期 >= 当前本次，且（若有结课时间）<= 结课
    const victims = settings.filter((s) => {
      const d = getDateOfSetting(s)
      if (!d) return false
      const dOnly = new Date(d.getFullYear(), d.getMonth(), d.getDate())
      const notBefore = dOnly.getTime() >= currentDateOnly.getTime()
      const notAfter = endDateOnly ? dOnly.getTime() <= endDateOnly.getTime() : true
      return notBefore && notAfter
    })

    if (!victims.length) {
      // 没找到符合的，按单次删除兜底
      await handleSingleCourseRemoval(baseItem.id!, day, period, session,
        getCellItems(day, period, session).findIndex((it) => it.id === baseItem.id)
      )
      ElMessage.success('仅删除了本次（未找到后续排课或已超过结课时间）')
      return
    }

    let ok = 0, fail = 0
    for (const s of victims) {
      try {
        await ClassSettingApi.deleteClassSetting(s.id)
        ok++
      } catch {
        fail++
      }
    }

    // 更新当前格子的 UI：去掉当前这条
    const arr = getCellItems(day, period, session)
    const remain = arr.filter((it) => it.id !== baseItem.id)
    setCellItems(day, period, session, remain)

    if (!ok) throw new Error('no success')
    ElMessage.success(`从本次起至结课删除完成：成功${ok}次${fail ? `，失败${fail}次` : ''}`)
  } catch (e) {
    console.error('handleForwardCourseRemoval error:', e)
    ElMessage.error('从本次起至结课删除失败，请重试')
  }
}


const removeVenueFor = async (day: DayKey, period: Period, session: number, idx: number) => {
  const arr = getCellItems(day, period, session)
  const it = arr[idx]
  if (!it?.id) return
  const oldVenue = it.venue
  const oldVenueId = it.venueId
  it.venue = null
  it.venueId = null
  try {
    await ClassSettingApi.updateClassSetting({
      id: it.id,
      classesId: it.classId,
      venueId: null,
      weekly: String(it.week),
      weekNumber: String(dayKeyToIndex[it.day]),
      sequence: String(toSequence(it.period, it.session)),
      yearNumber: String(it.year)
    })
    setCellItems(day, period, session, [...arr])
    ElMessage.success('场地已移除')
  } catch {
    it.venue = oldVenue
    it.venueId = oldVenueId
    setCellItems(day, period, session, [...arr])
    ElMessage.error('移除场地失败')
  }
}

const venueSearchQuery = reactive({ venueName: undefined as string | undefined })

const searchVenues = () => {
  const query = (venueSearchQuery.venueName ?? '').toString().trim().toLowerCase()
  if (!query) {
    displayVenues.value = [...venues.value]
  } else {
    displayVenues.value = venues.value.filter((v) =>
      (v.venueNo ?? '').toString().toLowerCase().includes(query)
    )
  }
}

const displayVenues = ref<any[]>([]) // 展示用

// ------- 初始化 -------
onMounted(async () => {
  await loadBasicData()
  currentWeek.value = getCurrentWeekOfYear()
  await getScheduleList()
})
</script>

<style scoped>
/* 样式保持不变，这里省略 */
/* ==================== 基础布局 ==================== */
.course-scheduler {
  position: relative;
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  background-color: #f5f7fa;
}

/* ==================== 组件内顶部悬浮班级列表 ==================== */
.floating-class-bar {
  position: sticky;
  top: 0;
  left: 0;
  right: 0;
  background: rgba(255, 255, 255, 0.98);
  backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--el-border-color-light);
  padding: 12px 20px;
  z-index: 100;
  display: flex;
  align-items: center;
  gap: 16px;
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.15);
  flex-shrink: 0;
}

.floating-class-bar .class-search {
  flex-shrink: 0;
  width: 200px;
}

.floating-class-bar .classes-row {
  display: flex;
  gap: 8px;
  overflow-x: auto;
  overflow-y: hidden;
  flex: 1;
  padding: 4px 0;
  scrollbar-width: thin;
  scrollbar-color: #c1c1c1 transparent;
}

.floating-class-bar .class-chip {
  display: flex;
  align-items: center;
  gap: 8px;
  background: #fff;
  border: 1px solid var(--el-border-color);
  border-radius: 6px;
  padding: 6px 10px;
  cursor: grab;
  transition: all 0.2s ease;
  flex-shrink: 0;
  white-space: nowrap;
  min-width: fit-content;
}

.floating-class-bar .class-chip:active {
  cursor: grabbing;
}

.floating-class-bar .class-chip:hover {
  transform: translateY(-1px);
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
  border-color: var(--el-color-primary);
}

/* ==================== 主体内容区域 ==================== */
.main-content {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
  overflow: hidden;
}

.content-inner {
  flex: 1;
  padding: 20px;
  display: flex;
  flex-direction: column;
  gap: 20px;
  overflow-y: auto;
}

/* ==================== 组件内底部悬浮场地列表 ==================== */
.floating-venue-bar {
  position: sticky;
  bottom: 0;
  left: 0;
  right: 0;
  background: rgba(255, 255, 255, 0.98);
  backdrop-filter: blur(12px);
  border-top: 1px solid var(--el-border-color-light);
  padding: 12px 20px;
  z-index: 100;
  box-shadow: 0 -2px 12px rgba(0, 0, 0, 0.15);
  flex-shrink: 0;
}

.floating-venue-bar .venues-row {
  display: flex;
  gap: 8px;
  overflow-x: auto;
  overflow-y: hidden;
  padding: 4px 0;
  justify-content: center;
  scrollbar-width: thin;
  scrollbar-color: #c1c1c1 transparent;
}

.floating-venue-bar .venue-chip {
  display: flex;
  align-items: center;
  background: #fff;
  border: 1px solid var(--el-border-color);
  border-radius: 6px;
  padding: 6px 10px;
  cursor: grab;
  transition: all 0.2s ease;
  flex-shrink: 0;
  white-space: nowrap;
  min-width: fit-content;
}

.floating-venue-bar .venue-chip:active {
  cursor: grabbing;
}

.floating-venue-bar .venue-chip:hover {
  transform: translateY(-1px);
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
  border-color: var(--el-color-success);
}

/* ==================== 顶部设置区域 ==================== */
.top-settings {
  display: flex;
  flex-direction: column;
  gap: 16px;
  flex-shrink: 0;
}

.settings-card {
  border-radius: 12px;
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
}

.settings-content {
  display: flex;
  align-items: center;
  gap: 40px;
  flex-wrap: wrap;
  padding: 8px 0;
}

.batch-mode-section,
.year-section {
  display: flex;
  align-items: center;
  gap: 16px;
  flex-shrink: 0;
}

.mode-label {
  font-weight: 500;
  color: var(--el-text-color-regular);
  white-space: nowrap;
}

.stats-section {
  display: flex;
  gap: 40px;
  align-items: center;
  flex-wrap: wrap;
}

.stat-item {
  text-align: center;
  flex-shrink: 0;
}

.stat-item :deep(.el-statistic__head) {
  font-size: 12px;
  color: var(--el-text-color-regular);
  margin-bottom: 4px;
}

.stat-item :deep(.el-statistic__content) {
  font-size: 20px;
  font-weight: 600;
}

/* ==================== 课程表主体 ==================== */
.schedule-main {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
}

.schedule-card {
  border-radius: 12px;
  flex: 1;
  display: flex;
  flex-direction: column;
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
}

.schedule-card :deep(.el-card__body) {
  flex: 1;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  padding: 16px;
}

.schedule-header-content {
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: 16px;
}

.card-header {
  display: flex;
  align-items: center;
  gap: 8px;
  font-weight: 600;
  color: var(--el-text-color-primary);
}

.week-controls {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-shrink: 0;
}

.week-info {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  font-weight: 500;
  color: var(--el-text-color-primary);
}

.week-number-section {
  display: flex;
  align-items: center;
  gap: 4px;
  font-size: 16px;
}

.week-number {
  font-size: 18px;
  color: var(--el-color-primary);
  font-weight: 600;
}

.week-date-section {
  font-size: 12px;
  color: var(--el-text-color-regular);
  text-align: center;
}

.week-date {
  background-color: var(--el-color-primary-light-9);
  padding: 2px 8px;
  border-radius: 12px;
  font-weight: normal;
}

.schedule-table-wrapper {
  flex: 1;
  overflow: auto;
  min-height: 0;
  position: relative;
  margin-top: 16px;
}

.schedule-table {
  display: flex;
  flex-direction: column;
  width: 100%;
  min-width: 900px;
  position: relative;
}

.schedule-header {
  display: grid;
  grid-template-columns: 80px repeat(7, minmax(140px, 1fr));
  gap: 8px;
  margin-bottom: 12px;
  position: sticky;
  top: 0;
  background: white;
  z-index: 20;
  padding: 4px 0;
}

.time-header,
.day-header {
  background-color: var(--el-color-primary-light-9);
  padding: 12px 8px;
  text-align: center;
  font-weight: 600;
  border-radius: 6px;
  color: var(--el-color-primary);
}

.schedule-body {
  position: relative;
  z-index: 1;
}

.time-period {
  margin-bottom: 16px;
  position: relative;
}

.time-row {
  display: grid;
  grid-template-columns: 80px repeat(7, minmax(140px, 1fr));
  gap: 8px;
  margin-bottom: 8px;
  position: relative;
}

/* 修改时间单元格为竖向显示 */
.time-cell.vertical-time {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 8px 4px;
  background-color: var(--el-color-info-light-9);
  border-radius: 6px;
  font-weight: 500;
  color: var(--el-color-info);
  font-size: 11px;
  min-height: 120px;
  width: 80px;
  gap: 4px;
}

.session-number {
  font-weight: 600;
  font-size: 12px;
  color: var(--el-text-color-primary);
}

.time-range {
  font-size: 10px;
  color: var(--el-text-color-regular);
  text-align: center;
  line-height: 1.2;
}

.period-indicator {
  font-size: 9px;
  padding: 2px 6px;
  border-radius: 10px;
  font-weight: 500;
}

.period-indicator.morning {
  background-color: var(--el-color-warning-light-8);
  color: var(--el-color-warning);
}

.period-indicator.afternoon {
  background-color: var(--el-color-success-light-8);
  color: var(--el-color-success);
}

/* ==================== 单元格样式 ==================== */
.schedule-cell {
  border: 2px dashed var(--el-border-color-light);
  border-radius: 8px;
  background-color: var(--el-bg-color-page);
  padding: 8px;
  min-height: 120px;
  max-height: 280px;
  overflow-y: auto;
  overflow-x: hidden;
  transition: all 0.2s ease;
  position: relative;
  z-index: 1;
}

.schedule-cell:hover {
  border-color: var(--el-color-primary-light-5);
  background-color: var(--el-color-primary-light-9);
}

.schedule-cell.has-content {
  border-color: var(--el-color-success);
  background-color: var(--el-color-success-light-9);
  border-style: solid;
}

.cell-content {
  display: flex;
  flex-direction: column;
  gap: 6px;
  position: relative;
  width: 100%;
  height: 100%;
}

/* 拖拽高亮 */
.schedule-cell.drag-over-course {
  background-color: var(--el-color-primary-light-8) !important;
  border-color: var(--el-color-primary) !important;
  border-style: solid !important;
  z-index: 10;
}

.schedule-cell.drag-over-venue {
  background-color: var(--el-color-success-light-8) !important;
  border-color: var(--el-color-success) !important;
  border-style: solid !important;
  z-index: 10;
}

/* 课程卡片 */
.course-zone {
  width: 100%;
  position: relative;
  z-index: 1;
}

.course-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  width: 100%;
  position: relative;
}

.course-card {
  display: flex;
  flex-direction: column;
  gap: 6px;
  background: #fff;
  border: 1px solid var(--el-border-color);
  border-radius: 8px;
  padding: 8px 10px;
  flex-shrink: 0;
  position: relative;
  z-index: 1;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.1);
}

.course-card:hover {
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
}

.course-card .row-1,
.course-card .row-2 {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  position: relative;
}

.mono {
  white-space: nowrap;
  font-family: var(--el-font-family-mono);
}

/* 空态 */
.empty-slot {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  color: var(--el-text-color-placeholder);
  font-size: 12px;
  opacity: 0.4;
  transition: opacity 0.3s ease;
  padding: 20px;
  text-align: center;
  position: relative;
}

.course-empty {
  color: var(--el-color-primary);
}

.venue-empty {
  color: var(--el-color-success);
}

.empty-text {
  font-size: 10px;
  text-align: center;
  margin-top: 2px;
}

.schedule-cell:hover .empty-slot {
  opacity: 0.7;
}

.drag-over-course .empty-slot.course-empty,
.drag-over-venue .empty-slot.venue-empty {
  opacity: 1;
  font-weight: bold;
  transform: scale(1.05);
}

/* ==================== 滚动条样式 ==================== */
.schedule-table-wrapper::-webkit-scrollbar,
.floating-class-bar .classes-row::-webkit-scrollbar,
.floating-venue-bar .venues-row::-webkit-scrollbar,
.schedule-cell::-webkit-scrollbar,
.content-inner::-webkit-scrollbar {
  width: 6px;
  height: 6px;
}

.schedule-table-wrapper::-webkit-scrollbar-track,
.floating-class-bar .classes-row::-webkit-scrollbar-track,
.floating-venue-bar .venues-row::-webkit-scrollbar-track,
.schedule-cell::-webkit-scrollbar-track,
.content-inner::-webkit-scrollbar-track {
  background: #f1f1f1;
  border-radius: 3px;
}

.schedule-table-wrapper::-webkit-scrollbar-thumb,
.floating-class-bar .classes-row::-webkit-scrollbar-thumb,
.floating-venue-bar .venues-row::-webkit-scrollbar-thumb,
.schedule-cell::-webkit-scrollbar-thumb,
.content-inner::-webkit-scrollbar-thumb {
  background: #c1c1c1;
  border-radius: 3px;
}

.schedule-table-wrapper::-webkit-scrollbar-thumb:hover,
.floating-class-bar .classes-row::-webkit-scrollbar-thumb:hover,
.floating-venue-bar .venues-row::-webkit-scrollbar-thumb:hover,
.schedule-cell::-webkit-scrollbar-thumb:hover,
.content-inner::-webkit-scrollbar-thumb:hover {
  background: #a8a8a8;
}

/* ==================== 响应式设计 ==================== */
@media (max-width: 1400px) {
  .settings-content {
    gap: 20px;
  }

  .stats-section {
    gap: 20px;
  }
}

@media (max-width: 768px) {
  .content-inner {
    padding: 12px;
    gap: 12px;
  }

  .floating-class-bar,
  .floating-venue-bar {
    padding: 8px 12px;
  }

  .floating-class-bar .class-search {
    width: 150px;
  }

  .schedule-header-content {
    flex-direction: column;
    align-items: stretch;
    gap: 12px;
  }

  .week-controls {
    justify-content: center;
  }

  .settings-content {
    flex-direction: column;
    align-items: stretch;
    gap: 16px;
  }

  .stats-section {
    justify-content: space-around;
    gap: 16px;
  }

  .schedule-table {
    min-width: 700px;
  }

  .schedule-header {
    grid-template-columns: 60px repeat(7, minmax(80px, 1fr));
  }

  .time-row {
    grid-template-columns: 60px repeat(7, minmax(80px, 1fr));
  }

  .time-cell.vertical-time {
    width: 60px;
    font-size: 10px;
  }
}

.venues-row {
  display: flex;
  align-items: center;
  gap: 8px;
  overflow: hidden;
}

.venue-search-fixed {
  flex-shrink: 0;
  width: 200px;
}

.venue-list-scrollable {
  display: flex;
  gap: 8px;
  overflow-x: auto;
  overflow-y: hidden;
  flex: 1;
  padding: 4px 0;
  scrollbar-width: thin;
  scrollbar-color: #c1c1c1 transparent;
}

.header-right {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-shrink: 0;
}

.year-select {
  min-width: 110px;
}

/* 让年份选择与右侧“第…周”匹配的浅主色胶囊风 */
.year-select {
  min-width: 120px;
}

/* 作用于 el-select 的输入外壳：圆角、浅底、主色文字与边框 */
:deep(.year-select .el-input__wrapper) {
  height: 32px; /* 与 size="small" 的圆形按钮高度对齐 */
  border-radius: 999px;
  background-color: var(--el-color-primary-light-9);
  box-shadow: inset 0 0 0 1px var(--el-color-primary-light-7);
  padding: 0 12px;
  transition:
    box-shadow 0.2s ease,
    background-color 0.2s ease,
    border-color 0.2s ease;
}

/* 前缀图标与文字主色强化，字号粗一点与“第…周”权重一致 */
:deep(.year-select .el-input__prefix),
:deep(.year-select .el-input__inner),
:deep(.year-select .el-select__caret) {
  color: var(--el-color-primary);
}

:deep(.year-select .el-input__inner) {
  font-weight: 600;
}

/* 悬浮与聚焦时强调边框，匹配 Element Plus 的交互风格 */
:deep(.year-select .el-input__wrapper:hover) {
  box-shadow: inset 0 0 0 1px var(--el-color-primary);
}

:deep(.year-select .el-input.is-focus .el-input__wrapper),
:deep(.year-select .el-input__wrapper.is-focus) {
  box-shadow: inset 0 0 0 2px var(--el-color-primary);
  background-color: var(--el-color-primary-light-9);
}

/* 下拉面板也稍作统一（可选） */
:deep(.year-select-popper .el-select-dropdown__item.is-selected) {
  color: var(--el-color-primary);
  font-weight: 600;
}

:deep(.year-select-popper .el-select-dropdown__item:hover) {
  background-color: var(--el-color-primary-light-9);
}
</style>
